﻿Imports System.Drawing
Imports System.ComponentModel

''' <summary>
''' Many thanks to VBHelper.com for this article
''' http://www.vb-helper.com/howto_net_component_collection_type_converter.html
''' Dario Solera for the DropDownPanel code
''' http://www.codeproject.com/Articles/11116/DropDownPanel-a-complete-Expandable-Panel
''' </summary>
''' <remarks></remarks>
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
<Serializable()> Public Class DDPanelStack
    Inherits System.Windows.Forms.Panel

#Region "Designer Generated Code"
    'UserControl overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private WithEvents components As System.Windows.Forms.Panel

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.components = New System.Windows.Forms.Panel()
        Me.SuspendLayout()
        '
        'components
        '
        Me.components.Location = New System.Drawing.Point(0, 0)
        Me.components.Name = "DropDownPanelStacked"
        Me.components.Size = New System.Drawing.Size(100, 23)
        Me.components.TabIndex = 0
        '
        'DropDownPanelStacked
        '
        Me.Name = "DropDownPanelStacked"
        Me.ResumeLayout(False)
    End Sub
#End Region

#Region "Declarations"
    'Internal Variables
    Private relocationAndResizeRequired As Boolean = True

    'Properties
    Protected WithEvents _PanelStack As New DDPanelCollection(Me)
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    Public Property PanelStack As DDPanelCollection
        Get
            Return _PanelStack
        End Get
        Set(value As DDPanelCollection)
            _PanelStack = value
            Me.RepositionAndResizeControls()
        End Set
    End Property
    Private _PaddingTopAndBottom As Integer = 5
    Public Property PaddingTopAndBottom As Integer
        Get
            Return _PaddingTopAndBottom
        End Get
        Set(value As Integer)
            _PaddingTopAndBottom = value
            Me.RepositionAndResizeControls()
        End Set
    End Property
    Private _PaddingLeft As Integer = 5
    Public Property PaddingLeft As Integer
        Get
            Return _PaddingLeft
        End Get
        Set(value As Integer)
            _PaddingLeft = value
            Me.RepositionAndResizeControls()
        End Set
    End Property
    Private _PaddingRight As Integer = 6
    Public Property PaddingRight As Integer
        Get
            Return _PaddingRight
        End Get
        Set(value As Integer)
            _PaddingRight = value
            Me.RepositionAndResizeControls()
        End Set
    End Property
    Private _ScrollBarSize As Integer = 18
    Public Property ScrollBarSize As Integer
        Get
            Return _ScrollBarSize
        End Get
        Set(value As Integer)
            _ScrollBarSize = value
            Me.RepositionAndResizeControls()
        End Set
    End Property

    'Ambient Properties
    Private _containerBackColor As Color = SystemColors.GradientInactiveCaption
    Public Property ContainerBackColor As Color
        Get
            Return Me._containerBackColor
        End Get
        Set(value As Color)
            Me._containerBackColor = value
            'Me.UpdateAmbientPropertyValues()
        End Set
    End Property
    Private _controlBackColor As Color = SystemColors.InactiveBorder
    Public Property ControlBackColor As Color
        Get
            Return Me._controlBackColor
        End Get
        Set(value As Color)
            Me._controlBackColor = value
            'Me.UpdateAmbientPropertyValues()
        End Set
    End Property
    Private _HeaderBackColorNormal As Color = SystemColors.Menu
    Public Property HeaderBackColorNormal As Color
        Get
            Return _HeaderBackColorNormal
        End Get
        Set(value As Color)
            _HeaderBackColorNormal = value
            'Me.UpdateAmbientPropertyValues()
        End Set
    End Property
    Private _HeaderBackColorHover As Color = SystemColors.Info
    Public Property HeaderBackColorHover As Color
        Get
            Return _HeaderBackColorHover
        End Get
        Set(value As Color)
            _HeaderBackColorHover = value
            'Me.UpdateAmbientPropertyValues()
        End Set
    End Property
    Private _ControlPositionIndex As Integer = 0
    Public ReadOnly Property ControlPositionIndex As Integer
        Get
            Return Me._ControlPositionIndex
        End Get
    End Property
#End Region

#Region "Constructors"
    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me.SetStyle(Windows.Forms.ControlStyles.SupportsTransparentBackColor, True)
        Me.SetStyle(Windows.Forms.ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(Windows.Forms.ControlStyles.ResizeRedraw, True)
        Me.MinimumSize = New Size(140, 100)
        Me.AutoScroll = True
    End Sub

#End Region

#Region "Handled Events"
    Private Sub _PanelStack_ItemAdded(sender As Object, e As DropDownPanelStackItemChangedArguments) Handles _PanelStack.ItemAdded
        Me.Controls.Add(e.Item)
        'UpdateAmbientPropertyValues()
        ResizeRelatedControls()
        RepositionAndResizeControls()
    End Sub
    Private Sub _PanelStack_ItemChanged(sender As Object, e As DropDownPanelStackItemChangedArguments) Handles _PanelStack.ItemChanged
        Me.Refresh()
        RepositionAndResizeControls()
    End Sub
    Private Sub _PanelStack_ItemRemoved(sender As Object, e As DropDownPanelStackItemChangedArguments) Handles _PanelStack.ItemRemoved
        Me.Controls.Remove(e.Item)
        ResizeRelatedControls()
        RepositionAndResizeControls()
    End Sub
    Private Sub _PanelStack_ItemsCleared(sender As Object, e As System.EventArgs) Handles _PanelStack.ItemsCleared
        Me.Controls.Clear()
    End Sub

#End Region

#Region "Private Procedures"
    Protected Friend Sub ResizeRelatedControls()
        Me.relocationAndResizeRequired = False

        'Get height estimate
        Dim itemHeight As Integer = (Me.Height _
                                    - (Me._PaddingTopAndBottom * _PanelStack.Count)) _
                                    / Me._PanelStack.Count

        For Each dPanel As DDPanel In Me._PanelStack
            dPanel.Size = New Size(dPanel.Size.Width, itemHeight)
        Next

        Me.relocationAndResizeRequired = True
    End Sub
    Protected Friend Sub RepositionAndResizeControls()

        If (Me._PanelStack.Count > 0) Then
            Me.SuspendLayout()
            Dim x, y, w, h As Integer
            x = _PaddingLeft + 1
            y = _PaddingTopAndBottom + 1
            If CType(Me, Windows.Forms.ScrollableControl).VerticalScroll.Visible Then
                w = Me.Size.Width - _PaddingLeft - _PaddingRight - _ScrollBarSize
            Else
                w = Me.Size.Width - _PaddingLeft - _PaddingRight
            End If
            If CType(Me, Windows.Forms.ScrollableControl).HorizontalScroll.Visible Then
                h = Me.Size.Height - (_PaddingTopAndBottom * 2) - _ScrollBarSize
            Else
                h = Me.Size.Height - (_PaddingTopAndBottom * 2)
            End If
            For i As Integer = 0 To Me._PanelStack.Count - 1
                Dim curControl As DDPanel = Me._PanelStack(i)
                curControl.Location = New Point(x, y)
                If curControl.LastPanel Then
                    Dim tot As Integer = _PaddingTopAndBottom
                    For z As Integer = 0 To _PanelStack.Count - 1
                        tot += _PanelStack(z).Size.Height + _PaddingTopAndBottom
                    Next
                    tot -= curControl.Size.Height - _PaddingTopAndBottom
                    curControl.Size = New Size(w, Me.Height - tot)
                Else
                    curControl.Size = New Size(w, curControl.Size.Height)
                End If
                y += (curControl.Size.Height + _PaddingTopAndBottom)
            Next

            Me.ResumeLayout()
        End If

    End Sub
    'Protected Friend Sub UpdateAmbientPropertyValues()
    '    For Each cnt As DDPanel In Me._PanelStack
    '        cnt.ContainerBackColor = Me.ContainerBackColor
    '        cnt.ControlBackColor = Me.ControlBackColor
    '        cnt.HeaderBackColorNormal = Me.HeaderBackColorNormal
    '        cnt.HeaderBackColorHover = Me.HeaderBackColorHover
    '    Next
    'End Sub
#End Region

#Region "Overrides"
    Protected Overrides Sub OnResize(eventargs As System.EventArgs)
        If Me.relocationAndResizeRequired Then Me.RepositionAndResizeControls()
        MyBase.OnResize(eventargs)
    End Sub
    Protected Overrides Sub OnLayout(levent As System.Windows.Forms.LayoutEventArgs)
        Me.RepositionAndResizeControls()
        MyBase.OnLayout(levent)
    End Sub
#End Region

End Class

'Collection class
<Serializable()> Public Class DDPanelCollection
    Inherits Collections.ObjectModel.Collection(Of DDPanel)
    'Implements IComparer

#Region "Declarations"
    'Variables
    Private _container As DDPanelStack = Nothing

    'Events
    Public Event ItemAdded(sender As Object, e As DropDownPanelStackItemChangedArguments)
    Public Event ItemChanged(sender As Object, e As DropDownPanelStackItemChangedArguments)
    Public Event ItemRemoved(sender As Object, e As DropDownPanelStackItemChangedArguments)
    Public Event ItemsCleared(sender As Object, e As System.EventArgs)
    Public Event ItemCollectionChanged(sender As Object, e As System.EventArgs)

    Private _IsAnimationRunning As Boolean

#End Region

#Region "Properties"
    Public ReadOnly Property IsAnimationRunning As Boolean
        Get
            Return Me._IsAnimationRunning
        End Get
    End Property
#End Region

#Region "Constructors"
    Private Sub New()
        'just to prevent empty object creation
    End Sub
    Public Sub New(container As DDPanelStack)
        Me._container = container
    End Sub
#End Region

#Region "Overrieds/Overloads"
    Private Shadows Property Controls As Windows.Forms.Form.ControlCollection

    Protected Overrides Sub ClearItems()
        MyBase.ClearItems()
        RaiseEvent ItemsCleared(Me, New System.EventArgs)
        RaiseEvent ItemCollectionChanged(Me, New EventArgs)
    End Sub

    Public Overloads Function Add(HeaderText As String) As Integer
        Dim dPanel As New DDPanel(Me, Me._container, HeaderText)
        'dPanel.ContainerBackColor = Me._container.ContainerBackColor
        'dPanel.ControlBackColor = Me._container.ControlBackColor
        'dPanel.HeaderBackColorNormal = Me._container.HeaderBackColorNormal
        'dPanel.HeaderBackColorHover = Me._container.HeaderBackColorHover
        MyBase.Add(dPanel)
        UpdateFirstLastPanels()
        AddHandler dPanel.HeaderTextChanged, AddressOf Items_HeaderTextChanged
        RaiseEvent ItemAdded(Me, New DropDownPanelStackItemChangedArguments(dPanel))
        RaiseEvent ItemCollectionChanged(Me, New EventArgs)
        Return MyBase.IndexOf(dPanel)
    End Function

    Protected Overrides Sub InsertItem(index As Integer, item As DDPanel)
        MyBase.InsertItem(index, item)
        UpdateFirstLastPanels()
        'item.ContainerBackColor = Me._container.ContainerBackColor
        'item.ControlBackColor = Me._container.ControlBackColor
        'item.HeaderBackColorNormal = Me._container.HeaderBackColorNormal
        'item.HeaderBackColorHover = Me._container.HeaderBackColorHover
        AddHandler item.HeaderTextChanged, AddressOf Items_HeaderTextChanged
        RaiseEvent ItemAdded(Me, New DropDownPanelStackItemChangedArguments(item))
        RaiseEvent ItemCollectionChanged(Me, New EventArgs)
    End Sub

    Protected Overrides Sub SetItem(index As Integer, item As DDPanel)
        MyBase.SetItem(index, item)
        UpdateFirstLastPanels()
        'item.ContainerBackColor = Me._container.ContainerBackColor
        'item.ControlBackColor = Me._container.ControlBackColor
        'item.HeaderBackColorNormal = Me._container.HeaderBackColorNormal
        'item.HeaderBackColorHover = Me._container.HeaderBackColorHover
        AddHandler item.HeaderTextChanged, AddressOf Items_HeaderTextChanged
        RaiseEvent ItemAdded(Me, New DropDownPanelStackItemChangedArguments(item))
        RaiseEvent ItemCollectionChanged(Me, New EventArgs)
    End Sub

    Protected Overrides Sub RemoveItem(index As Integer)
        Dim ddpanel As DDPanel = Me.Item(index)
        MyBase.RemoveItem(index)
        UpdateFirstLastPanels()
        RemoveHandler ddpanel.HeaderTextChanged, AddressOf Items_HeaderTextChanged
        RaiseEvent ItemRemoved(Me, New DropDownPanelStackItemChangedArguments(ddpanel))
        RaiseEvent ItemCollectionChanged(Me, New EventArgs)
    End Sub

    Private Sub Items_HeaderTextChanged(sender As DDPanel, e As System.EventArgs)
        RaiseEvent ItemChanged(Me, New DropDownPanelStackItemChangedArguments(sender))
        RaiseEvent ItemCollectionChanged(Me, New EventArgs)
    End Sub

#End Region

    Private Sub UpdateFirstLastPanels()
        For Each cnt As DDPanel In Me
            cnt.FirstPanel = False
            cnt.LastPanel = False
            cnt.ExpandOnClick = True
        Next
        'set last panel
        If Me.Count > 0 Then
            Me(0).FirstPanel = True
            Me(Me.Count - 1).LastPanel = True
            Me(Me.Count - 1).ExpandOnClick = False
        End If
    End Sub

#Region "IComparer Implementation"
    'Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare
    '    Dim xObj, yObj As DDPanel
    '    xObj = x
    '    yObj = y
    '    If xObj.ControlPositionIndex > yObj.ControlPositionIndex Then
    '        Return -1
    '    ElseIf xObj.ControlPositionIndex < yObj.ControlPositionIndex Then
    '        Return 1
    '    Else
    '        Return 0
    '    End If
    'End Function

#End Region

End Class

'Event arguments
Public Class DropDownPanelStackItemChangedArguments
    Inherits System.EventArgs

    Private _Item As DDPanel = Nothing
    Public Property Item As DDPanel
        Get
            Return Me._Item
        End Get
        Set(value As DDPanel)
            Me._Item = value
        End Set
    End Property

    Public Sub New(item As DDPanel)
        Me._Item = item
    End Sub

End Class
